// Record类型
// 用于定义`一个`对象类型，其所有属性名均为类型K，所有属性值均为类型T

// Record的底层代码
// 因为Record声明的是对象类型，而对象是属性名类型只支持：string | number | symbol，所以any会被推断为string | number | symbol
// [P in K]，在这表示循环的意思。将 泛型K 中的联合类型，一个个循环为属性名。
type Record<K extends keyof any, T> = { [P in K]: T };

// 1、统一对象属性名与属性值的类型
type User = Record<'name'| 'age' | 'address', string | number>
// 等价于
type User2 = { name: string | number, age: string | number, address: string | number }

// 2、Record定义的对象，当属性名类型为string或number时，包含了symbol。symbol则不包含 string与number
// 这是因为，对象的混合键类型时，开启了宽松的类型检查机制。参考10类型断言中的，对象的混合键类型
type Record_ = Record<string, string>
let obj: Record_ = {
  name: "张三",
  [Symbol("hello")]: true,
  0: "hello",
}

// 3、当Record类型的属性值为any时，声明后的变量，能够接受数组
let resArr: Record<string, any> = ["1", 0, true, {}]

// ### 作业，实现深拷贝
let res = {
  name: "张三",
  age: 18,
  isMale: true,
  info: { address: "广州" },
  saySomething: function(str: string) { console.log("你好, ", str) },
  children: [
    { name: "李四", age: 8 },
    { name: "李五", age: 2 },
  ]
}
type BaseType = string | number | boolean
function IsPlainObject(obj: any) {
  return Object.prototype.toString.call(obj).includes("Object")
}
function deepCopy(param: Record<string, any> | BaseType | Function) {
  let obj: any = undefined
  if (typeof param === 'object') {
    if (IsPlainObject(param)) {
      obj = {}
      for (let key in param) {
        obj[key] = deepCopy(param[key])
      }
    } else {
      obj = []
      param.forEach((item: any, index: number) => {
        obj[index] = deepCopy(item)
      })
    }
  } else {
    obj = param
  }
  return obj
}
let newRes = deepCopy(res)
export {}